// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// ina226 communicates with an ina226 sensor reading voltage, current and power.
package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"
	"log"
	"openzbox.com/driver/conn/i2c/i2creg"
	"openzbox.com/driver/devices/ina226"
	"openzbox.com/driver/host"
)

func checkError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func mainImpl() error {
	if _, err := host.Init(); err != nil {
		return err
	}
	address := flag.Int("address", 0x40, "I2C address")
	i2cbus := flag.String("bus", "/dev/i2c-0", "I2C bus (/dev/i2c-0)")

	flag.Parse()

	fmt.Println("Starting INA226 Current Sensor")
	if _, err := host.Init(); err != nil {
		return err
	}

	// Open default I2C bus.
	bus, err := i2creg.Open(*i2cbus)
	if err != nil {
		return fmt.Errorf("failed to open I2C: %v", err)
	}
	defer bus.Close()

	// Create a new power sensor a sense with default options of 100 mΩ, 3.2A at
	// address of 0x40 if no other address supplied with command line option.
	sensor, err := ina226.New(bus, &ina226.Opts{Address: *address})
	if err != nil {
		return fmt.Errorf("failed to open new sensor: %v", err)
	}
	err = sensor.Configure(ina226.INA226_SHUNT_CONV_TIME_1100US, ina226.INA226_BUS_CONV_TIME_1100US, ina226.INA226_AVERAGES_1, ina226.INA226_MODE_SHUNT_BUS_CONT)
	if err != nil {
		return fmt.Errorf("failed to open new sensor: %v", err)
	}
/*
	vBus, err := sensor.ReadBusVoltage()
	checkError(err)
	fmt.Printf("Bus voltage: %2.5f V\n", vBus)
	// measure the voltage drop across the shunt resistor
	vShunt, err := sensor.ReadShuntVoltage()
	checkError(err)
	fmt.Printf("Shunt voltage: %2.5f V\n", vShunt)
*/
	// If you want to read the current directly you must calibrate the sensor first
	// providing the Shunt resistor value (expressed in ohm) and
	// the maximum Expected current (expressed in Ampere).
	// This values are required to set the resolution of the readings
	sensor.Calibrate(0.1, 2.5)


	// Read values from sensor every second.
	everySecond := time.NewTicker(time.Second).C
	var halt = make(chan os.Signal, 1)
	signal.Notify(halt, syscall.SIGTERM)
	signal.Notify(halt, syscall.SIGINT)

	fmt.Println("ctrl+c to exit")
	for {
		select {
		case <-everySecond:
			p, err := sensor.Sense()
			if err != nil {
				return fmt.Errorf("sensor reading error: %v", err)
			}
			fmt.Println(p)
		case <-halt:
			return nil
		}
	}
}

func main() {
	if err := mainImpl(); err != nil {
		fmt.Fprintf(os.Stderr, "ina226: %s.\n", err)
		return
	}
}
